﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace KeyboardStatisticalTools
{
    public partial class MainForm : Form
    {
        #region 属性
        /// <summary>
        /// 键盘钩子
        /// </summary>
        KeyboardHook kh;
        /// <summary>
        /// sql字符串拼接
        /// </summary>
        StringBuilder strsql = new StringBuilder();
        /// <summary>
        /// 数据库连接
        /// </summary>
        DBHelp dbhelp = new DBHelp();
        /// <summary>
        /// 数据库参数类
        /// </summary>
        ParametersArray obParamLists = new ParametersArray();

        /// <summary>
        /// 数据存储
        /// </summary>
        DataSet ds = new DataSet();
        /// <summary>
        /// 总按键次数
        /// </summary>
        int keyPressSum = 0;
        #endregion

        #region 构造函数
        public MainForm()
        {
            InitializeComponent();
            //将此窗体设置为Topmost
            TopMostWindow.SetTopomost(this.Handle);
            //设置chart空间的样式
            chart1.Series[0].IsVisibleInLegend = false;
            //启动计时器
            timer1.Enabled = true;
        }
        #endregion

        #region 事件
        private void MainForm_Load(object sender, EventArgs e)
        {
            kh = new KeyboardHook();
            kh.SetHook();
            kh.OnKeyDownEvent += kh_OnKeyDownEvent;
            Rectangle ScreenArea = System.Windows.Forms.Screen.GetWorkingArea(this);
            int width1 = ScreenArea.Width; //屏幕宽度 
            int height1 = ScreenArea.Height; //屏幕高度
            this.Location = new System.Drawing.Point(width1 - this.Width, height1 - this.Height);  //指定窗体显示在右下角
        }
        private void kh_OnKeyDownEvent(object sender, KeyEventArgs e)
        {
            lblKeyCode.Text = e.KeyData.ToString();
            lblMsg.Text = "";
            strsql.Clear();
            InsertKeyToData(e);
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("确认退出吗？", "键盘统计", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
            {
                kh.UnHook();
                e.Cancel = true;
            }
        }

        private void btnSelect_Click(object sender, EventArgs e)
        {
            ds.Clear();
            strsql.Clear();
            strsql.Append("SELECT TOP 5 KeysName, KeysNum FROM (SELECT KeysName, COUNT(1) AS KeysNum");
            strsql.Append(" FROM TKeysCount GROUP BY KeysName) a ORDER BY KeysNum DESC");
            try
            {
                ds = dbhelp.GetDataSet(strsql.ToString());
                if (ds != null && ds.Tables.Count > 0 && ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                {
                    chart1.Series["按键次数"].Points.DataBind(ds.Tables[0].DefaultView, "KeysName", "KeysNum", "");
                    chart1.Series["按键次数"].ChartType = SeriesChartType.Bar;//图表类型  
                    chart1.DataBind();
                }
                else
                {
                    chart1.Series["按键次数"].Points.Clear();
                }
                strsql.Clear();
                strsql.Append("select count(1) from TKeysCount");
                int keyCount = 0;
                if (!int.TryParse(dbhelp.ExecuteScalar(strsql.ToString()).ToString(), out keyCount))
                {
                    lblMsg.Text = "转换查询结果失败。";
                }
                lblSumCount.Text = keyCount.ToString();
            }
            catch (Exception ex)
            {
                lblMsg.Text = ex.ToString();
            }
        }

        private void notifyIcon1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.notifyIcon1.Visible = false;
                this.ShowInTaskbar = true;
                this.WindowState = FormWindowState.Normal;
            }
        }

        private void MainForm_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.notifyIcon1.Visible = true;
                this.ShowInTaskbar = false;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            ds.Clear();
            strsql.Clear();
            strsql.Append("select count(1) from TKeysCount where PressTime between @StartTime and @EndTime");
            obParamLists.Par = new List<OleDbParameter>() { 
                    new OleDbParameter("@StartTime", DateTime.Now.AddMinutes(-1).ToString("yyyy-MM-dd HH:mm:ss")),
                    new OleDbParameter("@EndTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
                };

            if (int.TryParse(dbhelp.ExecuteScalar(strsql.ToString(), obParamLists).ToString(), out keyPressSum))
            {
                lblSpeed.Text = keyPressSum.ToString() + " 次/分钟";
            }
            else
            {
                lblSpeed.Text = "打字速度无法计算错误。";
            }
            obParamLists.Clear();
        }
        #endregion

        #region 方法
        /// <summary>
        /// 把按键记录插入数据库
        /// </summary>
        /// <param name="e">按键的事件</param>
        private void InsertKeyToData(KeyEventArgs e)
        {
            try
            {
                strsql.Append("insert into TKeysCount (KeysName,PressTime) values(@KeysName,@PressTime)");
                obParamLists.Par = new List<OleDbParameter>() { 
                    new OleDbParameter("@KeysName", e.KeyCode.ToString()),
                    new OleDbParameter("@PressTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
                };
                dbhelp.ExecuteNonQuery(strsql.ToString(), obParamLists);
                obParamLists.Clear();
            }
            catch (Exception ex)
            {
                lblMsg.Text = ex.Message;
            }
        }
        #endregion
    }
}
